/**********************************************************************************************************
** 驱动文件：	ups-GP800.c
** 驱动类型：	ups
** 设备名称：	科士达UPS
** 设备型号：	GP800
** 设备品牌：	科士达
** 设备协议：	RS232C 的智能单相UPS通信协议
** 驱动描述：	适用于科士达GP800系列UPS状态监测，协议类型为RS232C通信协议，指令为Q1<cr>
** 生成日期：	2018-10-26 11:10:25
**********************************************************************************************************/
#include "Includes.h"


/**********************************************************************************************************
* 定义设备数据点变量结构
**********************************************************************************************************/
typedef struct{
	Var InputVoltage;							//输入电压
	Var InputAbnormalVoltage;					//输入异常电压
	Var OutputVoltage;							//输出电压
	Var OutputCurrent;							//输出电流百分比
	Var InputFrequency;							//输入频率
	Var BatteryVoltage;							//单/总电池电压
	Var Temperature;							//温度
	Var ElectricityState;						//市电状态
	Var BatteryLowVoltage;						//电池低压
	Var BypassInvert;							//供电模式
	Var UPSFailure;								//UPS故障
	Var UPSType;								//UPS类型
	Var SystemTest;								//系统测试
	Var SystemShutdown;							//系统关机
}Data_Struct;									//定义变量结构


/**********************************************************************************************************
* 设备数据点变量属性声明
**********************************************************************************************************/
const static Var_Property_Def var_attr[] = {
	{
		FLOAT,
		0,
		READONLY,
		"InputVoltage",
		"输入电压",
		"V",
		"输入电压",
		0,
		0,
		"输入电压过高",
		"输入电压过低",
		0,
		0
	},
	{
		FLOAT,
		0,
		READONLY,
		"InputAbnormalVoltage",
		"输入异常电压",
		"V",
		"输入异常电压，对离线UPS：用于判定因产生的瞬时电压干扰使离线UPS 转为逆变模式的情况。对在线 UPS：是用于判定因瞬时出现的故障使在线UPS 转为电池模式的情况。",
		0,
		0,
		"",
		"",
		0,
		0
	},
	{
		FLOAT,
		0,
		READONLY,
		"OutputVoltage",
		"输出电压",
		"V",
		"输出电压",
		0,
		0,
		"输出电压过高",
		"输出电压过低",
		0,
		0
	},
	{
		INTEGER,
		0,
		READONLY,
		"OutputCurrent",
		"输出电流百分比",
		"%",
		"输出电流百分比值是一个相对于最大允许电流的百分比，非绝对值。",
		0,
		0,
		"输出电流过高",
		"输出电流过低",
		0,
		0
	},
	{
		FLOAT,
		0,
		READONLY,
		"InputFrequency",
		"输入频率",
		"Hz",
		"输入频率",
		0,
		0,
		"输入频率过高",
		"输入频率过低",
		0,
		0
	},
	{
		FLOAT,
		0,
		READONLY,
		"BatteryVoltage",
		"单/总电池电压",
		"V",
		"对于在线式UPS值为单体电池电压，对于后备式UPS值为总电池电压。",
		0,
		0,
		"电池电压过高",
		"电池电压过低",
		0,
		0
	},
	{
		FLOAT,
		0,
		READONLY,
		"Temperature",
		"温度",
		"℃",
		"环境温度",
		0,
		0,
		"温度过高",
		"温度过低",
		0,
		0
	},
	{
		OCTSTR,
		0,
		READONLY,
		"ElectricityState",
		"市电状态",
		"",
		"市电状态：市电正常、市电异常",
		0,
		0,
		"",
		"",
		0,
		0
	},
	{
		OCTSTR,
		0,
		READONLY,
		"BatteryLowVoltage",
		"电池低压",
		"",
		"电池电压低",
		0,
		0,
		"",
		"",
		0,
		0
	},
	{
		OCTSTR,
		0,
		READONLY,
		"BypassInvert",
		"供电模式",
		"",
		"供电模式：旁路供电、逆变供电",
		0,
		0,
		"",
		"",
		0,
		0
	},
	{
		OCTSTR,
		0,
		READONLY,
		"UPSFailure",
		"UPS故障",
		"",
		"UPS故障：正常、故障",
		0,
		0,
		"",
		"",
		0,
		0
	},
	{
		OCTSTR,
		0,
		READONLY,
		"UPSType",
		"UPS类型",
		"",
		"UPS类型：在线式、后备式",
		0,
		0,
		"",
		"",
		0,
		0
	},
	{
		OCTSTR,
		0,
		READONLY,
		"SystemTest",
		"系统测试",
		"",
		"系统测试：测试中，未测试",
		0,
		0,
		"",
		"",
		0,
		0
	},
	{
		OCTSTR,
		0,
		READONLY,
		"SystemShutdown",
		"系统关机",
		"",
		"系统关机：非关机状态、关机激活",
		0,
		0,
		"",
		"",
		0,
		0
	}
};


/**********************************************************************************************************
* 函数名称： static void cmd_fun(short index, int addr, void *data, char *cmd, short *len)
* 函数说明： 生成获取传感器数据指令
* 输入参数： 指令索引，传感器地址，变量结构体指针,以及指令缓存区指针,指令长度
* 返回参数： 无
**********************************************************************************************************/
static void cmd_fun(short index, int addr, void *data, char *cmd, short *len)
{
	switch(index)
	{
		case 0:
			*len = sprintf(cmd,"Q1\r");
			break;
		default:
			break;
	}
}


/**********************************************************************************************************
* 函数名称： static int parse_fun(short index, int addr, void *data, char *buf, short len)
* 函数说明： 解析传感器响应的数据，并写入数据库
* 输入参数： 解析索引,传感器地址，变量结构体指针，以及响应数据缓存取指针，响应数据长度
* 返回参数： 返回解析结果，返回0成功，返回1失败
**********************************************************************************************************/
static int parse_fun(short index, int addr, void *data, char *buf, short len)
{
	Data_Struct	*d = (Data_Struct*)data;

	if(buf!=NULL && len>0 && buf[0]=='(' && buf[len-1]=='\r'){
		switch(index){
			case 0:
				sscanf(buf,"(%f %f %f %d %f %f %f",
					&d->InputVoltage.value.fnum,
					&d->InputAbnormalVoltage.value.fnum,			
					&d->OutputVoltage.value.fnum,
					&d->OutputCurrent.value.inum,
					&d->InputFrequency.value.fnum,
					&d->BatteryVoltage.value.fnum,
					&d->Temperature.value.fnum
				);
				d->ElectricityState.value.str 			= buf[38]=='1'?"市电故障":"市电正常";
				Set_Var_Status(&d->ElectricityState, 	buf[38]=='1'?Alarm:Normal, NULL);	
				d->BatteryLowVoltage.value.str 			= buf[39]=='1'?"低压":"正常";
				Set_Var_Status(&d->BatteryLowVoltage, 	buf[39]=='1'?Alarm:Normal, NULL);			
				d->BypassInvert.value.str 				= buf[40]=='1'?"旁路供电":"逆变供电";
				Set_Var_Status(&d->BypassInvert, 		buf[40]=='1'?Alarm:Normal, NULL);			
				d->UPSFailure.value.str 				= buf[41]=='1'?"故障":"正常";
				Set_Var_Status(&d->UPSFailure, 			buf[41]=='1'?Alarm:Normal, NULL);			
				d->UPSType.value.str 					= buf[42]=='1'?"后备式":"在线式";
				Set_Var_Status(&d->UPSType, 			buf[42]=='1'?Alarm:Normal, NULL);
				d->SystemTest.value.str 				= buf[43]=='1'?"测试中":"未测试";
				Set_Var_Status(&d->SystemTest, 			buf[43]=='1'?Alarm:Normal, NULL);
				d->SystemShutdown.value.str 			= buf[44]=='1'?"关机激活":"非关机状态";
				Set_Var_Status(&d->SystemShutdown, 		buf[44]=='1'?Alarm:Normal, NULL);
				break;
			default:
				break;
		}
		return 0;
	}
	return 1;
}


/**********************************************************************************************************
* 函数名称： void ups_GP800_Registration(void)
* 函数说明： 科士达UPS监测驱动注册
* 输入参数： 无
* 返回参数： 无
**********************************************************************************************************/
void ups_GP800_Registration(void)
{
	DeviceDriverRegistration(
		"ups",													//设备类型
		"科士达UPS",											//设备名称（导航栏默认显示名称）
		"科士达",												//设备品牌
		"GP800",												//设备型号
		"适用于科士达GP800系列UPS状态监测，协议类型为RS232C通信协议，指令为Q1<cr>",//驱动描述
		var_attr,												//变量属性声明
		sizeof(Data_Struct),									//变量结构体空间大小
		cmd_fun,												//发送指令生成函数
		parse_fun,												//数据解析函数
		1000													//设备响应超时时间
	);
#if 0
	#define CMD1 "Q1\r"
	#define RSP1 "(208.4 140.0 208.4 034 59.9 2.05 35.0 00110000\r"	
	VirtualFrameRegistration(CMD1, sizeof(CMD1)-1, RSP1, sizeof(RSP1)-1);	
#endif	
}

